﻿using System.Collections.Generic;
using System.Linq;
using Foxit.PDF;
using Foxit.PDF.IO;
using Foxit.PDF.PageElements;
using Sustainalytics.ESG.Entities;
using Sustainalytics.Reporting.Framework;
using System;
using Sustainalytics.Entities.RiskRatings;

namespace Sustainalytics.RiskRatings.Reporting.Charts
{
    public enum ScatterChartType
    {
        Overview = 1,
        MatterialIssue = 2,
        Baseline = 3,
    }

    public class RiskRating_ScatterChart : PageElement
    {
        public float Left { get; set; }
        public float Top { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public bool ShowGridLines { get; set; }
        public List<RiskRatingPeer> SubPeerGroupBenchmark { get; set; }
        public List<SubIndustryRiskRatingPerformance> SubIndustryDataPoints { get; set; }
        public List<GlobalUniverseRiskRatingPerformance> GlobalUniverseDataPoints { get; set; }
        public ScatterChartType ChartType { get; set; }
        public double MeiManagament { get; set; }
        public double MeiExposure { get; set; }
        public Guid CompanyId { get; set; }
        public string SubIndustry { get; set; }
        public double MarketCapMin { get; set; }
        public double MarketCapMax { get; set; }
        public List<RiskRatingCluster> RiskRatingClusterList { get; set; }
        public double  SubIndustryAvgExposure { get; set; }
        public double SubIndustryAvgManagement { get; set; }
        public double SubIndustryMEIAvgExposure { get; set; }
        public double SubIndustryMEIAvgManagement { get; set; }

        public RiskRating_ScatterChart(float left, float top, float width)
        {
            Left = left;
            Top = top;
            Width = width;
            Height = width - 30;
            ChartType = ScatterChartType.MatterialIssue;
        }

        private Group Chart()
        {
            var pageElements = new Group();
            var leftOffset = 30.0f;
            var lineSize = 1f;
            var lineColor = RgbColor.Gray;
            var labelSize = 6f;
            float chartRootPointX = Left + leftOffset;
            float chartRootPointY = Top + Height;
            float maxValueY = 100;
            float maxValueX = ChartType == ScatterChartType.Overview ? 100 : 20;
            float pointWidthY = (Width - leftOffset) / maxValueY;
            float pointWidthX = (Width - leftOffset) / maxValueX;
            var circleSmallRadius = Width / 100 / 4;
            var circleMediumRadius = circleSmallRadius * 2f;
            var circleLargeRadius = circleSmallRadius * 4f;
            var globalUniversePointsColor = new RgbColor(204, 204, 204);
            var subIndustryPointsColor = new RgbColor(29, 96, 148);
            float left, top;
            var legendXOffset = Left + leftOffset;
            var legendYOffset = chartRootPointY + 30;

            // Add the axis
            pageElements.Add(new Rectangle(chartRootPointX, Top, Height, Height, lineColor, lineSize));

            // Add the chart labels
            pageElements.Add(
                new Label("Management", Left+15, chartRootPointY, Height, labelSize, Fonts.RobotoBold, labelSize, TextAlign.Center, RgbColor.Black)
                { Angle = -90 });
            pageElements.Add(
                new Label("Weak", Left+20, chartRootPointY, Height, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Right, RgbColor.Black)
                { Angle = -90 });
            pageElements.Add(
                new Label("Strong", Left+20, chartRootPointY, Height, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black)
                { Angle = -90 });
            pageElements.Add(
                new Label("Exposure", chartRootPointX, chartRootPointY + 10, Width - leftOffset, labelSize, Fonts.RobotoBold, labelSize, TextAlign.Center, RgbColor.Black));
            pageElements.Add(
                new Label("Low", chartRootPointX, chartRootPointY + 5, Width - leftOffset, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black));
            pageElements.Add(
                new Label("High", chartRootPointX, chartRootPointY + 5, Width - leftOffset, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Right, RgbColor.Black));

            // Add the chart dots
            foreach (GlobalUniverseRiskRatingPerformance point in GlobalUniverseDataPoints)
            {
                top = chartRootPointY - (maxValueY - (float)point.ManagementRisk) * pointWidthY;
                left = chartRootPointX + (float)point.Exposure * pointWidthX;
                pageElements.Add(new Circle(left, top, circleSmallRadius, globalUniversePointsColor, globalUniversePointsColor));
            }
            foreach (SubIndustryRiskRatingPerformance point in SubIndustryDataPoints)
            {
                top = chartRootPointY - (maxValueY - (float)point.ManagementRisk) * pointWidthY;
                left = chartRootPointX + (float)point.Exposure * pointWidthX;
                pageElements.Add(new Circle(left, top, circleMediumRadius, subIndustryPointsColor, subIndustryPointsColor));
            }

            RiskRatingPeer currentCompany = SubPeerGroupBenchmark.Find(x => x.CompanyId == CompanyId);
            if (currentCompany != null)
            {
                top = chartRootPointY - (maxValueY - (float)currentCompany.ManagementRisk) * pointWidthY;
                left = chartRootPointX + (float)currentCompany.Exposure * pointWidthX;
                pageElements.Add(new Circle(left, top, circleLargeRadius, RgbColor.Black, RgbColor.Black));
            }

            // Add the chart labels that should be on top of the dots
            pageElements.Add(
                new Label("Negligible Risk", chartRootPointX+5, chartRootPointY - 10, Width - leftOffset, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black));
            pageElements.Add(
                new Label("Severe Risk", chartRootPointX, Top + 5, Width - leftOffset - 5, labelSize, Fonts.RobotoRegular, labelSize, TextAlign.Right, RgbColor.Black));

            // Add the chart Legend items
            if (ChartType == ScatterChartType.Overview || ChartType==ScatterChartType.MatterialIssue)
            {
                pageElements.Add(new Circle(legendXOffset, legendYOffset, circleLargeRadius, circleLargeRadius, globalUniversePointsColor, globalUniversePointsColor, 1f, LineStyle.Solid));
                pageElements.Add(
                    new Label("Global Universe", legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));
                legendYOffset += 9;

                pageElements.Add(new Circle(legendXOffset, legendYOffset, circleLargeRadius, circleLargeRadius, subIndustryPointsColor, subIndustryPointsColor, 1f, LineStyle.Solid));
                pageElements.Add(
                    new Label(SubIndustry + " (Subindustry)", legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));

                legendYOffset += 9;
                pageElements.Add(new Circle(legendXOffset, legendYOffset, circleLargeRadius, circleLargeRadius, RgbColor.Black, RgbColor.Black, 1f, LineStyle.Solid));
                pageElements.Add(
                    new Label(currentCompany.CompanyName, legendXOffset + 5f, legendYOffset - 3, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));
                legendYOffset += 9;
                pageElements.Add(
                   new Label("+", legendXOffset-3f, legendYOffset-3f , 150, (float)TextSizes.RegularText+2, Fonts.RobotoRegular, (float)TextSizes.RegularText+2, TextAlign.Left, RgbColor.Orange));
                pageElements.Add(
                  new Label("SubIndustryAvg.", legendXOffset+5f, legendYOffset-3f, 150, (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText, TextAlign.Left, RgbColor.Black));


            }
            if (SubIndustryAvgManagement > 0 && SubIndustryAvgExposure > 0)
            {
                top = chartRootPointY - (maxValueY - (float)SubIndustryAvgManagement) * pointWidthY;
                left = chartRootPointX + (float)SubIndustryAvgExposure * pointWidthX;
                pageElements.Add(new Line(left, chartRootPointY, left, Top, 1f,RgbColor.Orange,LineStyle.Dash));
                pageElements.Add(new Line(chartRootPointX, top, chartRootPointX+Width-30f,top, 1f, RgbColor.Orange, LineStyle.Dash));
            }

            if (SubIndustryMEIAvgManagement > 0 && SubIndustryMEIAvgExposure > 0)
            {
                top = chartRootPointY - (maxValueY - (float)SubIndustryMEIAvgManagement) * pointWidthY;
                left = chartRootPointX + (float)SubIndustryMEIAvgExposure * pointWidthX;
                pageElements.Add(new Line(left, chartRootPointY, left, Top, 1f, RgbColor.Orange, LineStyle.Dash));
                pageElements.Add(new Line(chartRootPointX, top, chartRootPointX + Width - 30f, top, 1f, RgbColor.Orange, LineStyle.Dash));
            }


            return pageElements;
        }

        PageElement AddPeerToLegend_Mei(RiskRatingPeer legendItem, Guid companyId, float x, float y, float columnWidth)
        {
            Group root = new Group();
            RgbColor borderColor;
            RgbColor fillColor;
            RgbColor fontColor;
            var circleSmallRadius = columnWidth / 100;
            var circleLargeRadius = circleSmallRadius * 2f;
            var font = Fonts.RobotoRegular;
            var fontSize = 8;

            if (legendItem.CompanyId == companyId)
            {
                borderColor = RgbColor.Black;
                fillColor = RgbColor.Black;
                fontColor = RgbColor.White;
                font = Fonts.RobotoBold;
            }
            else
            {
                borderColor = RgbColor.Black;
                fillColor = RgbColor.White;
                fontColor = RgbColor.Black;
            }

            root.Add(new Line(x, y - 10, x + columnWidth, y - 10, 0.5f, RgbColor.Black, LineStyle.Dots));
            /*
            root.Add(new Circle(x, y, circleLargeRadius, circleLargeRadius, borderColor, fillColor, 1f, LineStyle.Solid));
            root.Add(new Label(string.Format("{0}", legendItem.Rank), x - 4f, y - 4.5f, 8f,
                    (float)TextSizes.RegularText, font, fontSize,
                    TextAlign.Center, fontColor));
            */
            var isLongName = Fonts.RobotoRegular.GetTextWidth(legendItem.CompanyName, fontSize) > columnWidth * 0.6f;
            root.Add(
                new TextArea(legendItem.CompanyName, x + circleLargeRadius * 2 - 2, y - (isLongName ? 7 : 4.5f), columnWidth * 0.6f,
                    fontSize * 2.5f, font, fontSize, TextAlign.Left, RgbColor.Black));

            if (legendItem.UnmanagedRisk != null)
            {
                var assesmentColor = ReportHelper.RiskClusterColors[legendItem.Assessment];
                root.Add(new Rectangle(x + columnWidth * 0.6f + 5, y - 5, 10, 10, assesmentColor, assesmentColor));
                root.Add(new Label(String.Format("{0:0.0}", legendItem.UnmanagedRisk), x + columnWidth * 0.6f + 20, y - 3f, 20f, fontSize, font, fontSize, TextAlign.Left, RgbColor.Black));
                root.Add(new Label(legendItem.Assessment.ToString(), x + columnWidth * 0.6f + 40, y - 3f, 50f, fontSize, font, fontSize, TextAlign.Left, RgbColor.Black));
            }
            else
            {
                root.Add(new Rectangle(x + columnWidth * 0.6f + 5, y - 5, 10, 10, RgbColor.Gray, RgbColor.Gray));
                root.Add(new Label("N/A", x + columnWidth * 0.6f + 20, y - 3f, 20f, fontSize, font, fontSize, TextAlign.Left, RgbColor.Black));
                root.Add(new Label("N/A", x + columnWidth * 0.6f + 40, y - 3f, 50f, fontSize, font, fontSize, TextAlign.Left, RgbColor.Black));
            }
            return root;
        }

        PageElement AddPeerToLegend_Overview(RiskRatingPeer legendItem, Guid companyId, int count, float x, float y, float columnWidth)
        {
            Group root = new Group();
            RgbColor borderColor;
            RgbColor fillColor;
            RgbColor fontColor;
            var circleSmallRadius = columnWidth / 100;
            var circleLargeRadius = circleSmallRadius * 2f;
            var currentYOffset = y;
            var left = count < 4 ? x : x + columnWidth / 2;


            if (legendItem.CompanyId == companyId)
            {
                borderColor = RgbColor.Black;
                fillColor = RgbColor.Black;
                fontColor = RgbColor.White;
            }
            else
            {
                borderColor = RgbColor.Black;
                fillColor = RgbColor.White;
                fontColor = RgbColor.Black;
            }

            left += 10;
            root.Add(new Circle(left, currentYOffset, circleLargeRadius, circleLargeRadius, borderColor, fillColor, 1f, LineStyle.Solid));

            root.Add(
                new Label(string.Format("{0}", legendItem.Rank), left - 4f, currentYOffset - 4f, 8f,
                    (float)TextSizes.RegularText, Fonts.RobotoRegular, (float)TextSizes.RegularText,
                    TextAlign.Center, fontColor));

            var isLongName = Fonts.RobotoRegular.GetTextWidth(legendItem.CompanyName, 6) > columnWidth * 0.45f;
            root.Add(
                new TextArea(legendItem.CompanyName, left + circleLargeRadius * 2 - 2, currentYOffset - (isLongName ? 6 : 4), columnWidth * 0.45f,
                    6 * 2 + 3, Fonts.RobotoRegular, 6, TextAlign.Left, RgbColor.Black));



            return root;
        }

        public override void Draw(PageWriter writer)
        {
            var chart = Chart();

            writer.Write_q_(true);
            chart.Draw(writer);
            writer.Write_Q(true);
        }
    }
}
